/*
* This file is part of the OpenJML project.
* Copyright (c) 2012-2013 David R. Cok
* @author David R. Cok
*/
package org.jmlspecs.openjml.eclipse.widgets;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
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.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.Shell;
import org.jmlspecs.annotation.Nullable;
/** Implements a dialog that allows the user to choose among the values of an Enum,
* using radio buttons.
* <P>
* Typical use for an Enum type E:<BR>
* <BR>EnumDialog<E> d = new EnumDialog<E>(shell, E.values(), null);
* <BR>d.create();
* <BR>if (d.open() == Dialog.OK) {
* <BR> E value = d.selection();
* <BR> ...
* <BR>}
* @param <E> the Enum whose values are being selected
*/
public class EnumDialog<E extends Enum<E>> extends Dialog {
/** Which elements are to be disabled */
protected EnumSet<E> disabled;
/** Which value is selected on exit from open() */
protected E selected;
/** Which values are to be included */
protected E[] values;
// Would like to subclass Button to add an E value - but that is not allowed;
// so we resort to a map
/** A map from buttons to their Enum values */
final protected Map<Button,E> buttonToValue = new HashMap<Button,E>();
/** The constructor for the dialog
* @param shell the parent shell, passed to the Dialog parent class
* @param values the values to display (e.g., E.values())
* @param disabled the values to disable (may be null, indicating nothing is disabled)
*/
public EnumDialog(Shell shell, E[] values, @Nullable EnumSet<E> disabled) {
super(shell);
this.values = values;
this.disabled = disabled;
}
// FIXME - need a way to add a title to these dialogs
@Override
public Control createDialogArea(Composite parent) {
Control c = super.createDialogArea(parent);
for (E v: values) { // Would rather say E.values(), but Java does not allow that
Button b = createRadioButton(parent,v,v.toString());
if (disabled != null) b.setEnabled(!disabled.contains(v));
}
return c;
}
/** The currently selected value */
public E selection() {
return selected;
}
/** Helper method to create individual radio buttons */
protected Button createRadioButton(Composite parent, E value, String label) {
final Button button = new Button(parent, SWT.RADIO);
buttonToValue.put(button, value);
button.setText(label); // JFaceResources.getString(key));
button.setFont(parent.getFont());
GridData data = new GridData(GridData.FILL_HORIZONTAL);
int widthHint = convertHorizontalDLUsToPixels(button,
IDialogConstants.BUTTON_WIDTH);
data.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT,
SWT.DEFAULT, true).x);
button.setLayoutData(data);
button.addSelectionListener(
new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
selected = buttonToValue.get(button);
}});
return button;
}
/** Helper method for layout */
protected int convertHorizontalDLUsToPixels(Control control, int dlus) {
GC gc = new GC(control);
gc.setFont(control.getFont());
int averageWidth = gc.getFontMetrics().getAverageCharWidth();
gc.dispose();
double horizontalDialogUnitSize = averageWidth * 0.25;
return (int) Math.round(dlus * horizontalDialogUnitSize);
}
}