/****************************************************************************** * Copyright (c) 2005, 2009 IBM Corporation 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 * * Contributors: * IBM Corporation - initial API and implementation * Nicolas Rouquette (NASA) - Fix for Bug 260812. ****************************************************************************/ package org.eclipse.gmf.runtime.diagram.ui.internal.dialogs.sortfilter; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.EditPolicy; import org.eclipse.gef.commands.Command; import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy; import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.ListCompartmentEditPart; import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles; import org.eclipse.gmf.runtime.diagram.ui.editpolicies.SortFilterContentEditPolicy; import org.eclipse.gmf.runtime.diagram.ui.internal.properties.Properties; import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages; import org.eclipse.gmf.runtime.diagram.ui.requests.ChangePropertyValueRequest; import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand; import org.eclipse.gmf.runtime.notation.Filtering; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; /** * Simple dialog that support filtering of list compartment items through visibililty * * @author jcorchis */ public class FilterDialog extends Dialog { /** dialog title prefix */ private final String title = DiagramUIMessages.SortFilterDialog_title; /** filter list labels */ static private final String FILTER_ITEMS_CONTAINING = DiagramUIMessages.SortFilter_filterItemsListLabel; static private final String FILTER_ITEMS_LIST = DiagramUIMessages.SortFilter_fitlerListLabel; /** Tool tips and labels for the filter buttons */ static private final String ADD_TO = DiagramUIMessages.SortFilter_addTo; private final String ADD_TO_LABEL = "<"; //$NON-NLS-1$ static private final String REMOVE_FROM = DiagramUIMessages.SortFilter_removeFrom; private final String REMOVE_FROM_LABEL = ">"; //$NON-NLS-1$ static private final String ADD_ALL = DiagramUIMessages.SortFilter_addAll; private final String ADD_ALL_LABEL = "<<"; //$NON-NLS-1$ static private final String REMOVE_ALL = DiagramUIMessages.SortFilter_removeAll; private final String REMOVE_ALL_LABEL = ">>"; //$NON-NLS-1$ static private final String APPLY = DiagramUIMessages.SortFilter_apply; /** List item widgets */ private org.eclipse.swt.widgets.List filterList = null; private org.eclipse.swt.widgets.List filters = null; private Button addTo = null; private Button removeFrom = null; private Button addAllTo = null; private Button removeAllFrom = null; /** Button IDs */ private final int ADD_TO_ID = 1000; private final int REMOVE_FROM_ID = ADD_TO_ID + 1; private final int ADD_ALL_TO_ID = ADD_TO_ID + 2; private final int REMOVE_ALL_FROM_ID = ADD_TO_ID + 3; private final int APPLY_ID = 5000; /** Height (in list items) for the filter items lists */ private int LIST_HEIGHT = 8; /** The collection Column list for this page */ private Map filterMap = null; private String[] filterStrings = null; /** the default fitlering settings */ private Filtering _filtering = Filtering.NONE_LITERAL; private List _filteringKeys = Collections.EMPTY_LIST; /** List of editpart selected */ private List selection; /** * Allows the user to initial apply changes and then * only after filtering has changed. */ private boolean changeToApply = true; /** * SelectionAdapter for the filtering buttons. Calls <code>buttonPressed()</code> * to handle the action. * * @author jcorchis */ class ButtonSelectionAdapter extends SelectionAdapter { public void widgetSelected(SelectionEvent event) { buttonPressed(((Integer) event.widget.getData()).intValue()); } } /** Instance of the ButtonSelectionAdapter used for all filtering buttons. */ private ButtonSelectionAdapter buttonSelectionAdapter = new ButtonSelectionAdapter(); /** * @param parentShell */ protected FilterDialog(Shell parentShell, List selection, Map filterMap) { super(parentShell); this.selection = selection; this.filterMap = filterMap; } /** * Adds an apply button and the filter control * @see org.eclipse.jface.dialogs.Dialog#createContents(org.eclipse.swt.widgets.Composite) */ protected Control createDialogArea(Composite parent) { getShell().setText(title); createFilterLists(parent); return parent; } /** * Adds the apply button * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) */ protected void createButtonsForButtonBar(Composite parent) { super.createButtonsForButtonBar(parent); createButton(parent, APPLY_ID, APPLY, true); } /** * Creates the filtering list widgets * @param parent */ private void createFilterLists(Composite ancestor) { // Do not show the filter lists if not filter criteria // is defined. if (filterMap == null || filterMap.isEmpty()) return; Object[] filterArray = filterMap.keySet().toArray(); this.filterStrings = new String[filterArray.length]; for (int i = 0; i < filterArray.length; i++) { filterStrings[i] = (String) filterArray[i]; } //setup layout Composite parent = new Composite(ancestor, SWT.NULL); GridLayout layout = new GridLayout(); layout.marginHeight = 10; layout.marginWidth = 10; layout.numColumns = 3; parent.setLayout(layout); // Create the possible filter items list Label filterItemsLabel = new Label(parent, SWT.LEFT); filterItemsLabel.setText(FILTER_ITEMS_CONTAINING); GridData gd = new GridData(); gd.horizontalAlignment = GridData.HORIZONTAL_ALIGN_BEGINNING; filterItemsLabel.setLayoutData(gd); // Create the possible filter items list new Label(parent, SWT.LEFT); // Create the possible filter items list Label filterItemLabel = new Label(parent, SWT.LEFT); filterItemLabel.setText(FILTER_ITEMS_LIST); GridData gd2 = new GridData(); gd2.horizontalAlignment = GridData.BEGINNING; filterItemLabel.setLayoutData(gd2); // Create the possible filter items list filters = new org.eclipse.swt.widgets.List( parent, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_FILL); gridData.verticalSpan = 1; gridData.widthHint = 80; int listHeight = filters.getItemHeight() * LIST_HEIGHT; Rectangle trim = filters.computeTrim(0, 0, 0, listHeight); gridData.heightHint = trim.height; filters.setLayoutData(gridData); // Create a new composite for the buttons and add // stack them vertically Composite buttonComposite = new Composite(parent, SWT.NULL); GridLayout buttonLayout = new GridLayout(); buttonLayout.marginHeight = 0; buttonLayout.marginWidth = 0; buttonLayout.numColumns = 1; buttonComposite.setLayout(buttonLayout); GridData buttGD = new GridData(GridData.FILL_VERTICAL | GridData.CENTER); buttGD.horizontalSpan = 1; buttGD.widthHint = 30; buttonComposite.setLayoutData(buttGD); removeFrom = new Button(buttonComposite, SWT.PUSH); removeFrom.setText(REMOVE_FROM_LABEL); removeFrom.setToolTipText(REMOVE_FROM); removeFrom.setLayoutData(makeArrowButtonGridData(removeFrom)); removeFrom.setData(new Integer(REMOVE_FROM_ID)); removeFrom.addSelectionListener(buttonSelectionAdapter); removeFrom.setEnabled(false); addTo = new Button(buttonComposite, SWT.PUSH); addTo.setText(ADD_TO_LABEL); addTo.setToolTipText(ADD_TO); addTo.setLayoutData(makeArrowButtonGridData(addTo)); addTo.setData(new Integer(ADD_TO_ID)); addTo.addSelectionListener(buttonSelectionAdapter); addTo.setEnabled(false); removeAllFrom = new Button(buttonComposite, SWT.PUSH); removeAllFrom.setText(REMOVE_ALL_LABEL); removeAllFrom.setToolTipText(REMOVE_ALL); removeAllFrom.setLayoutData(makeArrowButtonGridData(removeAllFrom)); removeAllFrom.setData(new Integer(REMOVE_ALL_FROM_ID)); removeAllFrom.addSelectionListener(buttonSelectionAdapter); addAllTo = new Button(buttonComposite, SWT.PUSH); addAllTo.setText(ADD_ALL_LABEL); addAllTo.setToolTipText(ADD_ALL); addAllTo.setLayoutData(makeArrowButtonGridData(addAllTo)); addAllTo.setData(new Integer(ADD_ALL_TO_ID)); addAllTo.addSelectionListener(buttonSelectionAdapter); // Add the possible list of filter items this.filterList = new org.eclipse.swt.widgets.List( parent, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL); GridData gridData2 = new GridData(GridData.VERTICAL_ALIGN_FILL); gridData2.verticalSpan = 1; gridData2.widthHint = 80; int listHeight2 = filterList.getItemHeight() * LIST_HEIGHT; Rectangle trim2 = filterList.computeTrim(0, 0, 0, listHeight2); gridData.heightHint = trim2.height; filterList.setLayoutData(gridData2); filters.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { removeFrom.setEnabled(filters.getSelectionCount() > 0); } }); filterList.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { addTo.setEnabled(filterList.getSelectionCount() > 0); } }); initFilterLists(); } /** * Populates the filter lists based on the _filteringKeys * and the filter criteria. */ private void initFilterLists() { // TODO match the filtering key for all the list compartments if (filterMap != null && !filterMap.isEmpty()) { Set keySet = filterMap.keySet(); Iterator i = keySet.iterator(); if (_filtering == Filtering.AUTOMATIC_LITERAL) { // Set the values of the filtered and unfiltered string while (i.hasNext()) { String filterString = (String) i.next(); if (_filteringKeys.contains(filterString)) { filters.add(filterString); } else { filterList.add(filterString); } } } else { // Add all filter strings to the possible filter list while (i.hasNext()) { String filterString = (String) i.next(); filterList.add(filterString); } } } } /** * Creates GridData for the moveup and movedown toolbar buttons. * @param control button * @return the <code>GridData</code> */ protected GridData makeArrowButtonGridData(Control control) { GC gc = new GC(control); gc.setFont(control.getFont()); //fill horizontal to make them all the same size GridData gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.heightHint = 24; gc.dispose(); return gridData; } /** * * @param filterMap * @param property */ public void setFilter(Map filterMap, String property) { if (filterMap != null) { this.filterMap = filterMap; Object[] filterArray = filterMap.keySet().toArray(); this.filterStrings = new String[filterArray.length]; for (int i = 0; i < filterArray.length; i++) { filterStrings[i] = (String) filterArray[i]; } } } /** * Handles the button pressed event on the filter criteria. Move the items * between the lists based on the selection and but button pressed. * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int) */ protected void buttonPressed(int buttonId) { String[] items = { }; switch (buttonId) { case ADD_TO_ID : items = filterList.getSelection(); for (int i = 0; i < items.length; i++) { filters.add(items[i]); filterList.remove(items[i]); } addTo.setEnabled(false); changeToApply = true; break; case REMOVE_FROM_ID : items = filters.getSelection(); for (int i = 0; i < items.length; i++) { filterList.add(items[i]); filters.remove(items[i]); } removeFrom.setEnabled(false); changeToApply = true; break; case ADD_ALL_TO_ID : items = filterList.getItems(); for (int i = 0; i < items.length; i++) { filters.add(items[i]); filterList.remove(items[i]); } changeToApply = true; break; case REMOVE_ALL_FROM_ID : items = filters.getItems(); for (int i = 0; i < items.length; i++) { filters.remove(items[i]); filterList.add(items[i]); } changeToApply = true; break; case IDialogConstants.OK_ID : okPressed(); break; case APPLY_ID : applyPressed(); break; default: super.buttonPressed(buttonId); } } /** * */ protected void okPressed() { if (changeToApply) applyPressed(); super.okPressed(); } /** * Executes a sort filter command for every list compartment that understands * the sort filter request. */ protected void applyPressed() { if (!changeToApply) return; if (filters.getItemCount() > 0) { _filteringKeys = new ArrayList(); _filtering = Filtering.AUTOMATIC_LITERAL; for (int i = 0; i < filters.getItemCount(); i++) { _filteringKeys.add(filters.getItems()[i]); } } else { _filtering = Filtering.NONE_LITERAL; _filteringKeys = Collections.EMPTY_LIST; } ChangePropertyValueRequest filterTypeRequest = new ChangePropertyValueRequest( Properties.ID_FILTERING, Properties.ID_FILTERING, _filtering); ChangePropertyValueRequest filterKeysRequest = new ChangePropertyValueRequest( Properties.ID_FILTERING_KEYS, Properties.ID_FILTERING_KEYS, _filteringKeys); // Run the command TransactionalEditingDomain editingDomain = null; List childCommands = new ArrayList(); Iterator iter = selection.iterator(); while (iter.hasNext()) { GraphicalEditPart ep = (GraphicalEditPart) iter.next(); if (editingDomain == null) { editingDomain = ep.getEditingDomain(); } List children = ep.getChildren(); for (int i = 0; i < children.size(); i++) { if (children.get(i) instanceof ListCompartmentEditPart) { ListCompartmentEditPart editPart = (ListCompartmentEditPart) children .get(i); if (filterMap != null && filterMap.equals(getFilterMapFromEditPart(editPart))) { Command command = editPart.getCommand(filterTypeRequest); if (null != command) { childCommands.add(new CommandProxy(command)); } command = editPart.getCommand(filterKeysRequest); if (null != command) { childCommands.add(new CommandProxy(command)); } } } } } CompositeTransactionalCommand cc = new CompositeTransactionalCommand(editingDomain, DiagramUIMessages.Command_SortFilterCommand, childCommands); ((IGraphicalEditPart) selection.get(0)).getRoot().getViewer() .getEditDomain().getCommandStack().execute( new ICommandProxy(cc)); changeToApply = false; } /** * Returns the ListCompartment level filter map or Collections.EMPTY_MAP * if an EditPolicyRoles.SORT_FILTER_CONTENT_ROLE is not installed * on the ListCompartment. * @param editPart * @return Map the filter map */ private Map getFilterMapFromEditPart(ListCompartmentEditPart editPart) { EditPolicy ep = editPart.getEditPolicy(EditPolicyRoles.SORT_FILTER_CONTENT_ROLE); if (ep instanceof SortFilterContentEditPolicy) { return ((SortFilterContentEditPolicy)ep).getFilter(); } return Collections.EMPTY_MAP; } }