/****************************************************************************** * Copyright (c) 2009-2013, Linagora * * 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: * Linagora - initial API and implementation *******************************************************************************/ package com.ebmwebsourcing.petals.common.internal.provisional.ui; import java.util.Arrays; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; import org.eclipse.jface.viewers.StyledCellLabelProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; 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; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.AbstractElementListSelectionDialog; import org.eclipse.ui.dialogs.ISelectionStatusValidator; import org.eclipse.ui.dialogs.SelectionStatusDialog; import com.ebmwebsourcing.petals.common.internal.provisional.swt.StyledFilteredList; /** * An element list selection dialog that supports {@link StyledCellLabelProvider}s. * <p> * The code was taken from {@link AbstractElementListSelectionDialog} and modified * to work with {@link StyledFilteredList}s. * </p> * * @contributor Vincent Zurczak - EBM WebSourcing */ public class StyledElementListSelectionDialog extends SelectionStatusDialog { // // Code from AbstractElementListSelectionDialog // // VZ: changed the type of the renderer private final IStyledLabelProvider fRenderer; private boolean fIgnoreCase = true; private boolean fIsMultipleSelection = false; private Label fMessage; // VZ protected StyledFilteredList fFilteredList; // VZ private Text fFilterText; private ISelectionStatusValidator fValidator; private String fFilter = null; private String fEmptyListMessage = ""; //$NON-NLS-1$ private String fEmptySelectionMessage = ""; //$NON-NLS-1$ private int fWidth = 60; private int fHeight = 18; private Object[] fSelection = new Object[0]; /** * Constructs a list selection dialog. * @param parent The parent for the list. * @param renderer ILabelProvider for the list */ // VZ: changed the name, visibility and parameter type in the constructor public StyledElementListSelectionDialog( Shell parent, IStyledLabelProvider renderer ) { super( parent ); this.fRenderer = renderer; } /** * Handles default selection (double click). * By default, the OK button is pressed. */ protected void handleDefaultSelected() { if (validateCurrentSelection()) { buttonPressed(IDialogConstants.OK_ID); } } /** * Specifies if sorting, filtering and folding is case sensitive. * @param ignoreCase */ public void setIgnoreCase(boolean ignoreCase) { this.fIgnoreCase = ignoreCase; } /** * Returns if sorting, filtering and folding is case sensitive. * @return boolean */ public boolean isCaseIgnored() { return this.fIgnoreCase; } /** * Specifies if multiple selection is allowed. * @param multipleSelection */ public void setMultipleSelection(boolean multipleSelection) { this.fIsMultipleSelection = multipleSelection; } /** * Sets the list size in unit of characters. * @param width the width of the list. * @param height the height of the list. */ public void setSize(int width, int height) { this.fWidth = width; this.fHeight = height; } /** * Sets the message to be displayed if the list is empty. * @param message the message to be displayed. */ public void setEmptyListMessage(String message) { this.fEmptyListMessage = message; } /** * Sets the message to be displayed if the selection is empty. * @param message the message to be displayed. */ public void setEmptySelectionMessage(String message) { this.fEmptySelectionMessage = message; } /** * Sets an optional validator to check if the selection is valid. * The validator is invoked whenever the selection changes. * @param validator the validator to validate the selection. */ public void setValidator(ISelectionStatusValidator validator) { this.fValidator = validator; } /** * Sets the elements of the list (widget). * To be called within open(). * @param elements the elements of the list. */ protected void setListElements(Object[] elements) { this.fFilteredList.setElements(elements); } /** * Sets the filter pattern. * @param filter the filter pattern. */ public void setFilter(String filter) { if (this.fFilterText == null) { this.fFilter = filter; } else { this.fFilterText.setText(filter); } } /** * Returns the current filter pattern. * @return returns the current filter pattern or <code>null<code> if filter was not set. */ public String getFilter() { if (this.fFilteredList == null) { return this.fFilter; } return this.fFilteredList.getFilter(); } /** * Sets the selection referenced by an array of elements. * Empty or null array removes selection. * To be called within open(). * @param selection the indices of the selection. */ protected void setSelection(Object[] selection) { Assert.isNotNull(this.fFilteredList); this.fFilteredList.setSelection(selection); } /** * Returns an array of the currently selected elements. * To be called within or after open(). * @return returns an array of the currently selected elements. */ protected Object[] getSelectedElements() { Assert.isNotNull(this.fFilteredList); return this.fFilteredList.getSelection(); } /** * Creates the message text widget and sets layout data. * @param composite the parent composite of the message area. */ @Override protected Label createMessageArea(Composite composite) { Label label = super.createMessageArea(composite); GridData data = new GridData(); data.grabExcessVerticalSpace = false; data.grabExcessHorizontalSpace = true; data.horizontalAlignment = GridData.FILL; data.verticalAlignment = GridData.BEGINNING; label.setLayoutData(data); this.fMessage = label; return label; } /** * Handles a selection changed event. * By default, the current selection is validated. */ protected void handleSelectionChanged() { validateCurrentSelection(); } /** * Validates the current selection and updates the status line * accordingly. * @return boolean <code>true</code> if the current selection is * valid. */ protected boolean validateCurrentSelection() { Assert.isNotNull(this.fFilteredList); IStatus status; Object[] elements = getSelectedElements(); if (elements.length > 0) { if (this.fValidator != null) { status = this.fValidator.validate(elements); } else { status = new Status(IStatus.OK, PlatformUI.PLUGIN_ID, IStatus.OK, "", //$NON-NLS-1$ null); } } else { if (this.fFilteredList.isEmpty()) { status = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.ERROR, this.fEmptyListMessage, null); } else { status = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.ERROR, this.fEmptySelectionMessage, null); } } updateStatus(status); return status.isOK(); } /* * @see Dialog#cancelPressed */ @Override protected void cancelPressed() { setResult(null); super.cancelPressed(); } /** * Creates a filtered list. * @param parent the parent composite. * @return returns the filtered list widget. */ protected StyledFilteredList createFilteredList(Composite parent) { int flags = SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | (this.fIsMultipleSelection ? SWT.MULTI : SWT.SINGLE); StyledFilteredList list = new StyledFilteredList( parent, flags, this.fRenderer ); GridData data = new GridData(); data.widthHint = convertWidthInCharsToPixels(this.fWidth); data.heightHint = convertHeightInCharsToPixels(this.fHeight); data.grabExcessVerticalSpace = true; data.grabExcessHorizontalSpace = true; data.horizontalAlignment = GridData.FILL; data.verticalAlignment = GridData.FILL; list.setLayoutData(data); list.setFont(parent.getFont()); list.setFilter((this.fFilter == null ? "" : this.fFilter)); //$NON-NLS-1$ list.addSelectionListener(new SelectionListener() { @Override public void widgetDefaultSelected(SelectionEvent e) { handleDefaultSelected(); } @Override public void widgetSelected(SelectionEvent e) { handleWidgetSelected(); } }); this.fFilteredList = list; return list; } // 3515 private void handleWidgetSelected() { Object[] newSelection = this.fFilteredList.getSelection(); if (newSelection.length != this.fSelection.length) { this.fSelection = newSelection; handleSelectionChanged(); } else { for (int i = 0; i != newSelection.length; i++) { if (!newSelection[i].equals(this.fSelection[i])) { this.fSelection = newSelection; handleSelectionChanged(); break; } } } } protected Text createFilterText(Composite parent) { Text text = new Text(parent, SWT.BORDER); GridData data = new GridData(); data.grabExcessVerticalSpace = false; data.grabExcessHorizontalSpace = true; data.horizontalAlignment = GridData.FILL; data.verticalAlignment = GridData.BEGINNING; text.setLayoutData(data); text.setFont(parent.getFont()); text.setText((this.fFilter == null ? "" : this.fFilter)); //$NON-NLS-1$ Listener listener = new Listener() { @Override public void handleEvent(Event e) { StyledElementListSelectionDialog.this.fFilteredList.setFilter(StyledElementListSelectionDialog.this.fFilterText.getText()); } }; text.addListener(SWT.Modify, listener); text.addKeyListener(new KeyListener() { @Override public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.ARROW_DOWN) { StyledElementListSelectionDialog.this.fFilteredList.setFocus(); } } @Override public void keyReleased(KeyEvent e) { } }); this.fFilterText = text; return text; } /* * (non-Javadoc) * @see org.eclipse.jface.window.Window#open() */ @Override public int open() { super.open(); return getReturnCode(); } private void access$superCreate() { super.create(); } /* * (non-Javadoc) * @see org.eclipse.jface.window.Window#create() */ @Override public void create() { BusyIndicator.showWhile(null, new Runnable() { @Override public void run() { access$superCreate(); Assert.isNotNull(StyledElementListSelectionDialog.this.fFilteredList); if (StyledElementListSelectionDialog.this.fFilteredList.isEmpty()) { handleEmptyList(); } else { validateCurrentSelection(); StyledElementListSelectionDialog.this.fFilterText.selectAll(); StyledElementListSelectionDialog.this.fFilterText.setFocus(); } } }); } /** * Handles empty list by disabling widgets. */ protected void handleEmptyList() { this.fMessage.setEnabled(false); this.fFilterText.setEnabled(false); this.fFilteredList.setEnabled(false); updateOkState(); } /** * Update the enablement of the OK button based on whether or not there * is a selection. * */ protected void updateOkState() { Button okButton = getOkButton(); if (okButton != null) { okButton.setEnabled(getSelectedElements().length != 0); } } /** * Gets the optional validator used to check if the selection is valid. * The validator is invoked whenever the selection changes. * @return the validator to validate the selection, or <code>null</code> * if no validator has been set. * * @since 3.5 */ protected ISelectionStatusValidator getValidator() { return this.fValidator; } // Code from ElementListSelectionDialog private Object[] fElements; /** * Sets the elements of the list. * @param elements the elements of the list. */ public void setElements(Object[] elements) { this.fElements = elements == null ? new Object[ 0 ] : Arrays.copyOf( elements, elements.length ); } /* * @see SelectionStatusDialog#computeResult() */ @Override protected void computeResult() { setResult(Arrays.asList(getSelectedElements())); } /* * @see Dialog#createDialogArea(Composite) */ @Override protected Control createDialogArea(Composite parent) { Composite contents = (Composite) super.createDialogArea(parent); createMessageArea(contents); createFilterText(contents); createFilteredList(contents); setListElements(this.fElements); setSelection(getInitialElementSelections().toArray()); return contents; } }