/**
* Copyright 2014 SAP AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spotter.eclipse.ui.dialogs;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.spotter.eclipse.ui.util.WidgetUtils;
/**
* An abstract dialog to add components.
*
* @author Denis Knoepfle
*
*/
public abstract class AbstractAddDialog extends TitleAreaDialog {
private final class ElementLabelProvider extends LabelProvider {
/**
* Returns the name of the element provided by the implementing class of
* the dialog.
*
* @param element
* the element the name is retrieved for
*/
@Override
public String getText(Object element) {
return AbstractAddDialog.this.getElementName(element);
}
}
private static final String MSG_NO_SELECT = "No elements selected.";
private static final String MSG_MULTI_SELECT = "Selected %d elements.";
private static final String MSG_NO_DESCRIPTION = "No description available.";
private static final Point INITIAL_DIALOG_SIZE = new Point(580, 380);
private static final int TABLE_VIEWER_RATIO = 55;
private static final int DESCRIPTION_RATIO = 45;
private final Object[] viewerInput;
private Object[] result;
private TableViewer viewer;
private Text textDescription;
/**
* Creates the dialog under the given parent shell. Turns available help
* off. The given input is sorted alphabetically using the names of the
* elements.
*
* @param parentShell
* The parent shell of this dialog
* @param viewerInput
* the input for the dialog's table viewer. May be
* <code>null</code> for zero elements.
*/
public AbstractAddDialog(Shell parentShell, Object[] viewerInput) {
super(parentShell);
if (viewerInput == null) {
this.viewerInput = new Object[0];
} else {
this.viewerInput = viewerInput;
Arrays.sort(this.viewerInput, createInputComparator());
}
this.result = null;
setHelpAvailable(false);
}
/**
* Implementing classes must provide a name for the given element.
*
* @param element
* target element
* @return the name of the given element
*/
protected abstract String getElementName(Object element);
/**
* Implementing classes must provide a description for the given element or
* <code>null</code> if none.
*
* @param element
* target element
* @return the description of the given element or <code>null</code> if none
*/
protected abstract String getElementDescription(Object element);
/**
* Create contents of the dialog.
*
* @param parent
* The parent composite the content is placed in
* @return a {@link Control} instance
*/
@Override
protected Control createDialogArea(Composite parent) {
Composite area = (Composite) super.createDialogArea(parent);
Composite container = new Composite(area, SWT.NONE);
container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
container.setLayout(WidgetUtils.createFillLayout(SWT.HORIZONTAL));
SashForm sashContainer = new SashForm(container, SWT.HORIZONTAL | SWT.SMOOTH);
Composite tableComp = new Composite(sashContainer, SWT.NONE);
tableComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
TableColumnLayout tableColLayout = new TableColumnLayout();
tableComp.setLayout(tableColLayout);
viewer = new TableViewer(tableComp, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL);
TableViewerColumn tableColumn = new TableViewerColumn(viewer, SWT.NONE);
tableColLayout.setColumnData(tableColumn.getColumn(), new ColumnWeightData(1));
tableColumn.getColumn().setResizable(false);
tableColumn.getColumn().setMoveable(false);
viewer.getTable().setLinesVisible(false);
viewer.setContentProvider(new ArrayContentProvider());
viewer.setLabelProvider(new ElementLabelProvider());
viewer.setInput(viewerInput);
createTableListeners();
textDescription = new Text(sashContainer, SWT.WRAP | SWT.V_SCROLL | SWT.READ_ONLY);
if (viewerInput.length > 0) {
viewer.getTable().setSelection(0);
updateDescriptionText(viewerInput[0]);
}
sashContainer.setWeights(new int[] { TABLE_VIEWER_RATIO, DESCRIPTION_RATIO });
return area;
}
private Comparator<Object> createInputComparator() {
Comparator<Object> comparator = new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
String name1 = getElementName(o1);
String name2 = getElementName(o2);
return name1.compareTo(name2);
}
};
return comparator;
}
private void updateDescriptionText(Object element) {
String description = getElementDescription(element);
textDescription.setText(description == null ? MSG_NO_DESCRIPTION : description);
}
private void createTableListeners() {
final Table table = viewer.getTable();
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
int selectionCount = table.getSelectionCount();
getButton(Window.OK).setEnabled(selectionCount > 0);
if (selectionCount == 0) {
textDescription.setText(MSG_NO_SELECT);
} else if (selectionCount == 1) {
int index = table.getSelectionIndex();
updateDescriptionText(viewerInput[index]);
} else if (selectionCount > 1) {
textDescription.setText(String.format(MSG_MULTI_SELECT, selectionCount));
}
}
});
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseDoubleClick(MouseEvent e) {
int itemCount = table.getItemCount();
int itemHeight = table.getItemHeight();
if (e.y <= itemCount * itemHeight) {
okPressed();
}
}
});
}
/**
* Create contents of the button bar.
*
* @param parent
* parent composite
*/
@Override
protected void createButtonsForButtonBar(Composite parent) {
createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
getButton(Window.OK).setEnabled(viewerInput.length > 0);
}
/**
* Return the initial size of the dialog.
*
* @return the initial size of the dialog.
*/
@Override
protected Point getInitialSize() {
return INITIAL_DIALOG_SIZE;
}
@Override
protected void okPressed() {
Table table = viewer.getTable();
int selectionCount = table.getSelectionCount();
if (selectionCount != 0) {
result = new Object[selectionCount];
int[] indices = table.getSelectionIndices();
for (int i = 0; i < selectionCount; ++i) {
result[i] = viewerInput[indices[i]];
}
}
super.okPressed();
}
/**
* Returns the previously selected elements if any or <code>null</code>.
*
* @return the previously selected elements if any or <code>null</code>
*/
public Object[] getResult() {
return result;
}
}