/*****************************************************************************
* Copyright (c) 2010 CEA LIST.
*
* 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:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
*****************************************************************************/
package org.eclipse.papyrus.infra.widgets.editors;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.SelectObservableValue;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.papyrus.infra.widgets.messages.Messages;
import org.eclipse.papyrus.infra.widgets.providers.IStaticContentProvider;
import org.eclipse.papyrus.infra.widgets.providers.MapLabelProvider;
import org.eclipse.papyrus.infra.widgets.providers.StaticContentProvider;
import org.eclipse.swt.SWT;
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;
/**
* An editor representing an Enumeration as a list of Radio Buttons
* If there are many possible values, it is probably more judicious to use an
* EnumCombo.
* This Editor needs a ContentProvider describing the Enumerated values,
* and an optional label provider.
*
* @author Camille Letavernier
*
* @see EnumCombo
*/
public class EnumRadio extends AbstractValueEditor {
protected IStaticContentProvider contentProvider;
protected Composite buttonsArea;
protected ILabelProvider labelProvider = new LabelProvider();
protected final Map<Button, Object> values = new HashMap<Button, Object>();
protected int numColumns = -1;
public EnumRadio(Composite parent, int style) {
this(parent, SWT.NONE, null);
}
public EnumRadio(Composite parent, int style, String label) {
super(parent, style, label);
buttonsArea = factory.createComposite(this);
buttonsArea.setLayoutData(getDefaultLayoutData());
GridLayout layout = new GridLayout(1, true);
layout.marginWidth = 0;
layout.marginHeight = 0;
buttonsArea.setLayout(layout);
factory.createCLabel(buttonsArea, Messages.EnumRadio_NoValue);
}
/**
* Sets the content provider for this editor. The Content provider should
* specify the values that can be set for this property
*
* @param contentProvider
* The Content provider returning the available values for this editor
* @param labelProvider
* The label provider returning a label for each value of the
* content provider. If null, a default label provider will be used
*/
public void setProviders(IStaticContentProvider contentProvider, ILabelProvider labelProvider) {
this.contentProvider = contentProvider;
if(labelProvider != null) {
this.labelProvider = labelProvider;
}
disposeButtons();
if(widgetObservable != null) {
widgetObservable.dispose();
}
SelectObservableValue observable = new SelectObservableValue();
for(Object value : contentProvider.getElements()) {
Button button = factory.createButton(buttonsArea, labelProvider.getText(value), SWT.RADIO);
button.setBackground(buttonsArea.getBackground()); //For Radio buttons, we need to force the color
button.setData(value);
button.setToolTipText(toolTipText);
IObservableValue buttonObservable = WidgetProperties.selection().observe(button);
observable.addOption(value, buttonObservable);
values.put(button, value);
}
setWidgetObservable(observable, true);
updateLayout();
doBinding();
}
protected void disposeButtons() {
for(Control control : buttonsArea.getChildren()) {
control.dispose();
}
if(binding != null) {
binding.dispose();
}
values.clear();
}
/**
* Sets the max number of elements per line for this editor
*
* @param numColumns
* The max number of elements per line. May be -1 if there should
* be a single line of elements
*/
public void setNumColumns(int numColumns) {
this.numColumns = numColumns;
updateLayout();
}
private void updateLayout() {
GridLayout gridLayout = (GridLayout)buttonsArea.getLayout();
gridLayout.numColumns = numColumns > 0 ? numColumns : values.size();
gridLayout.makeColumnsEqualWidth = numColumns > 0;
updateLabelLayout();
}
private void updateLabelLayout() {
if(label == null || label.isDisposed()) {
return;
}
if(numColumns == -1) {
((GridData)label.getLayoutData()).verticalAlignment = SWT.CENTER;
} else {
((GridData)label.getLayoutData()).verticalAlignment = SWT.BEGINNING;
}
}
@Override
protected void createLabel(String label) {
super.createLabel(label);
updateLabelLayout();
}
@Override
public Object getValue() {
for(Button button : values.keySet()) {
if(button.getSelection()) {
return values.get(button);
}
}
return null;
}
@Override
public Object getEditableType() {
return Object.class;
}
@Override
public void setReadOnly(boolean readOnly) {
for(Button button : values.keySet()) {
button.setEnabled(!readOnly);
}
buttonsArea.setEnabled(!readOnly);
}
@Override
public boolean isReadOnly() {
return !buttonsArea.isEnabled();
}
@Override
public void setToolTipText(String text) {
for(Button button : values.keySet()) {
button.setToolTipText(text);
}
super.setLabelToolTipText(text);
}
public void setValue(Object value) {
if(modelProperty != null) {
modelProperty.setValue(value);
}
if(widgetObservable != null) {
widgetObservable.setValue(value);
} else {
for(Button button : values.keySet()) {
if(values.get(button) == value) {
button.setSelection(true);
return;
}
}
}
}
/**
* Use a Map instead of content providers to define the selectable elements
* The keys are the semantic objects (contentProvider), and the values are
* the labels (labelProvider)
*
* @param objectsAndLabels
*/
public void setEnumValues(Map<Object, String> objectsAndLabels) {
StaticContentProvider provider = new StaticContentProvider(objectsAndLabels.keySet().toArray());
LabelProvider labelProvider = new MapLabelProvider(objectsAndLabels);
setProviders(provider, labelProvider);
}
}