blob: 38bc11a64c80912f10f76cf4d42834b9d433e12e [file] [log] [blame]
/**
* Copyright (c) 2002-2007 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 - Initial API and implementation
*/
package org.eclipse.emf.edit.ui.provider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ICellEditorValidator;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.graphics.Image;
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.Text;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.emf.common.ui.celleditor.ExtendedComboBoxCellEditor;
import org.eclipse.emf.common.ui.celleditor.ExtendedDialogCellEditor;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.util.Diagnostician;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.emf.edit.ui.EMFEditUIPlugin;
import org.eclipse.emf.edit.ui.celleditor.FeatureEditorDialog;
/**
* This is used to encapsulate an {@link IItemPropertyDescriptor} along with the object for which it is an item property source
* and make it behave like an {@link org.eclipse.ui.views.properties.IPropertyDescriptor}.
*/
public class PropertyDescriptor implements IPropertyDescriptor
{
/**
* This is the object for which this class is a property source.
*/
protected Object object;
/**
* This is the descriptor to which we will delegate all the {@link org.eclipse.ui.views.properties.IPropertyDescriptor} methods.
*/
protected IItemPropertyDescriptor itemPropertyDescriptor;
/**
* An instance is constructed from an object and its item property source.
*/
public PropertyDescriptor(Object object, IItemPropertyDescriptor itemPropertyDescriptor)
{
this.object = object;
this.itemPropertyDescriptor = itemPropertyDescriptor;
}
public String getCategory()
{
return itemPropertyDescriptor.getCategory(object);
}
public String getDescription()
{
return itemPropertyDescriptor.getDescription(object);
}
public String getDisplayName()
{
return itemPropertyDescriptor.getDisplayName(object);
}
public String[] getFilterFlags()
{
return itemPropertyDescriptor.getFilterFlags(object);
}
public Object getHelpContextIds()
{
return itemPropertyDescriptor.getHelpContextIds(object);
}
/**
* Provides direct access to the underlying feature object.
*
* @since 2.9
*/
public Object getFeature()
{
return itemPropertyDescriptor.getFeature(object);
}
public Object getId()
{
return itemPropertyDescriptor.getId(object);
}
public ILabelProvider getLabelProvider()
{
final IItemLabelProvider itemLabelProvider = itemPropertyDescriptor.getLabelProvider(object);
return
new LabelProvider()
{
@Override
public String getText(Object object)
{
return itemLabelProvider.getText(object);
}
@Override
public Image getImage(Object object)
{
return ExtendedImageRegistry.getInstance().getImage(itemLabelProvider.getImage(object));
}
};
}
protected ILabelProvider getEditLabelProvider()
{
return getLabelProvider();
}
public boolean isCompatibleWith(IPropertyDescriptor anotherProperty)
{
return false;
}
/**
* A delegate for handling validation and conversion for data type values.
*/
protected static class EDataTypeValueHandler implements ICellEditorValidator, IInputValidator
{
protected EDataType eDataType;
public EDataTypeValueHandler(EDataType eDataType)
{
this.eDataType = eDataType;
}
public String isValid(Object object)
{
Object value;
try
{
value = eDataType.getEPackage().getEFactoryInstance().createFromString(eDataType, (String)object);
}
catch (Exception exception)
{
String message = exception.getClass().getName();
int index = message.lastIndexOf('.');
if (index >= 0)
{
message = message.substring(index + 1);
}
if (exception.getLocalizedMessage() != null)
{
message = message + ": " + exception.getLocalizedMessage();
}
return message;
}
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eDataType, value);
if (diagnostic.getSeverity() == Diagnostic.OK)
{
return null;
}
else
{
return (diagnostic.getChildren().get(0)).getMessage().replaceAll("'","''").replaceAll("\\{", "'{'"); // }}
}
}
public String isValid(String text)
{
return isValid((Object)text);
}
public Object toValue(String string)
{
return EcoreUtil.createFromString(eDataType, string);
}
public String toString(Object value)
{
String result = EcoreUtil.convertToString(eDataType, value);
return result == null ? "" : result;
}
}
public static class EDataTypeCellEditor extends TextCellEditor
{
protected EDataType eDataType;
protected EDataTypeValueHandler valueHandler;
public EDataTypeCellEditor(EDataType eDataType, Composite parent)
{
super(parent);
this.eDataType = eDataType;
valueHandler = new EDataTypeValueHandler(eDataType);
setValidator(valueHandler);
}
@Override
public Object doGetValue()
{
return valueHandler.toValue((String)super.doGetValue());
}
@Override
public void doSetValue(Object value)
{
value = valueHandler.toString(value);
super.doSetValue(value);
}
// CellEditor.setValue() calls isCorrect() to validate the value that is about to be set. We are doing conversion
// between the value and a corresponding string, and we would usually like to validate the string. Because
// setValue() is final, we cannot do that conversion there, so we need to record what we're trying to validate and
// work around the problem in isCorrect().
//
protected boolean validateAsValue = true;
@Override
protected void editOccured(ModifyEvent e)
{
validateAsValue = false;
super.editOccured(e);
validateAsValue = true;
}
@Override
protected boolean isCorrect(Object value)
{
if (validateAsValue)
{
value = valueHandler.toString(value);
}
return super.isCorrect(value);
}
}
private static class MultiLineInputDialog extends InputDialog
{
public MultiLineInputDialog(Shell parentShell, String title, String message, String initialValue, IInputValidator validator)
{
super(parentShell, title, message, initialValue, validator);
setShellStyle(getShellStyle() | SWT.RESIZE);
}
@Override
protected Text createText(Composite composite)
{
Text text = new Text(composite, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
data.heightHint = 5 * text.getLineHeight();
data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.ENTRY_FIELD_WIDTH);
text.setLayoutData(data);
return text;
}
}
protected CellEditor createEDataTypeCellEditor(final EDataType eDataType, Composite composite)
{
if (itemPropertyDescriptor.isMultiLine(object))
{
return new ExtendedDialogCellEditor(composite, getEditLabelProvider())
{
protected EDataTypeValueHandler valueHandler = new EDataTypeValueHandler(eDataType);
@Override
protected Object openDialogBox(Control cellEditorWindow)
{
InputDialog dialog = new MultiLineInputDialog
(cellEditorWindow.getShell(),
EMFEditUIPlugin.INSTANCE.getString
("_UI_FeatureEditorDialog_title", new Object [] { getDisplayName(), getEditLabelProvider().getText(object) }),
EMFEditUIPlugin.INSTANCE.getString("_UI_MultiLineInputDialog_message"),
valueHandler.toString(getValue()),
valueHandler);
return dialog.open() == Window.OK ? valueHandler.toValue(dialog.getValue()) : null;
}
};
}
return new EDataTypeCellEditor(eDataType, composite);
}
/**
* This cell editor ensures that only Integer values are supported
* @deprecated
*/
@Deprecated
public static class IntegerCellEditor extends TextCellEditor
{
public IntegerCellEditor(Composite composite)
{
super(composite);
setValidator
(new ICellEditorValidator()
{
public String isValid(Object object)
{
if (object instanceof Integer)
{
return null;
}
else
{
String string = (String)object;
try
{
Integer.parseInt(string);
return null;
}
catch (NumberFormatException exception)
{
return exception.getMessage();
}
}
}
});
}
@Override
public Object doGetValue()
{
return Integer.parseInt((String)super.doGetValue());
}
@Override
public void doSetValue(Object value)
{
super.doSetValue(value.toString());
}
}
/**
* This cell editor ensures that only Float values are supported
* @deprecated
*/
@Deprecated
public static class FloatCellEditor extends TextCellEditor
{
public FloatCellEditor(Composite composite)
{
super(composite);
setValidator
(new ICellEditorValidator()
{
public String isValid(Object object)
{
if (object instanceof Float)
{
return null;
}
else
{
String string = (String)object;
try
{
Float.parseFloat(string);
return null;
}
catch (NumberFormatException exception)
{
return exception.getMessage();
}
}
}
});
}
@Override
public Object doGetValue()
{
return new Float(Float.parseFloat((String)super.doGetValue()));
}
@Override
public void doSetValue(Object value)
{
super.doSetValue(value.toString());
}
}
protected static final EcorePackage ecorePackage = EcorePackage.eINSTANCE;
/**
* This returns the cell editor that will be used to edit the value of this property.
* This default implementation determines the type of cell editor from the nature of the structural feature.
*/
public CellEditor createPropertyEditor(Composite composite)
{
if (!itemPropertyDescriptor.canSetProperty(object))
{
return null;
}
CellEditor result = null;
Object genericFeature = itemPropertyDescriptor.getFeature(object);
if (genericFeature instanceof EReference[])
{
result = new ExtendedComboBoxCellEditor(
composite,
new ArrayList<Object>(itemPropertyDescriptor.getChoiceOfValues(object)),
getEditLabelProvider(),
itemPropertyDescriptor.isSortChoices(object));
}
else if (genericFeature instanceof EStructuralFeature)
{
final EStructuralFeature feature = (EStructuralFeature)genericFeature;
final EClassifier eType = feature.getEType();
final Collection<?> choiceOfValues = itemPropertyDescriptor.getChoiceOfValues(object);
if (choiceOfValues != null)
{
if (itemPropertyDescriptor.isMany(object))
{
boolean valid = true;
for (Object choice : choiceOfValues)
{
if (!eType.isInstance(choice))
{
valid = false;
break;
}
}
if (valid)
{
final ILabelProvider editLabelProvider = getEditLabelProvider();
result =
new ExtendedDialogCellEditor(composite, editLabelProvider)
{
@Override
protected Object openDialogBox(Control cellEditorWindow)
{
FeatureEditorDialog dialog = new FeatureEditorDialog(
cellEditorWindow.getShell(),
editLabelProvider,
object,
feature.getEType(),
(List<?>)doGetValue(),
getDisplayName(),
new ArrayList<Object>(choiceOfValues),
false,
itemPropertyDescriptor.isSortChoices(object),
feature.isUnique() || feature instanceof EReference);
dialog.open();
return dialog.getResult();
}
};
}
}
if (result == null)
{
result =
new ExtendedComboBoxCellEditor
(composite, new ArrayList<Object>(choiceOfValues), getEditLabelProvider(), itemPropertyDescriptor.isSortChoices(object));
}
}
else if (eType instanceof EDataType)
{
EDataType eDataType = (EDataType)eType;
if (eDataType.isSerializable())
{
if (itemPropertyDescriptor.isMany(object))
{
final ILabelProvider editLabelProvider = getEditLabelProvider();
result =
new ExtendedDialogCellEditor(composite, editLabelProvider)
{
@Override
protected Object openDialogBox(Control cellEditorWindow)
{
FeatureEditorDialog dialog = new FeatureEditorDialog(
cellEditorWindow.getShell(),
editLabelProvider,
object,
feature.getEType(),
(List<?>)doGetValue(),
getDisplayName(),
null,
itemPropertyDescriptor.isMultiLine(object),
false,
feature.isUnique());
dialog.open();
return dialog.getResult();
}
};
}
else if (eDataType.getInstanceClass() == Boolean.class)
{
result = new ExtendedComboBoxCellEditor(
composite,
Arrays.asList(new Object [] { null, Boolean.FALSE, Boolean.TRUE }),
getEditLabelProvider(),
itemPropertyDescriptor.isSortChoices(object));
}
else if (eDataType.getInstanceClass() == Boolean.TYPE)
{
result = new ExtendedComboBoxCellEditor(
composite,
Arrays.asList(new Object [] { Boolean.FALSE, Boolean.TRUE }),
getEditLabelProvider(),
itemPropertyDescriptor.isSortChoices(object));
}
else
{
result = createEDataTypeCellEditor(eDataType, composite);
}
}
}
}
return result;
}
}