/** * 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); } public Object getId() { return itemPropertyDescriptor.getId(object); } public ILabelProvider getLabelProvider() { final IItemLabelProvider itemLabelProvider = itemPropertyDescriptor.getLabelProvider(object); return new LabelProvider() { private static final long serialVersionUID = 1L; @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 { /** * */ private static final long serialVersionUID = 1L; 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 { /** * */ private static final long serialVersionUID = 1L; 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 { /** * */ private static final long serialVersionUID = 1L; 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()) { /** * */ private static final long serialVersionUID = 1L; 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 { /** * */ private static final long serialVersionUID = 1L; public IntegerCellEditor(Composite composite) { super(composite); setValidator (new ICellEditorValidator() { /** * */ private static final long serialVersionUID = 1L; 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 { /** * */ private static final long serialVersionUID = 1L; public FloatCellEditor(Composite composite) { super(composite); setValidator (new ICellEditorValidator() { /** * */ private static final long serialVersionUID = 1L; 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) { /** * */ private static final long serialVersionUID = 1L; @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()); 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) { /** * */ private static final long serialVersionUID = 1L; @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 [] { Boolean.FALSE, Boolean.TRUE }), getEditLabelProvider(), itemPropertyDescriptor.isSortChoices(object)); } else if (eDataType.getInstanceClass() == Boolean.TYPE) { result = new ExtendedComboBoxCellEditor( composite, Arrays.asList(new Object [] { null, Boolean.FALSE, Boolean.TRUE }), getEditLabelProvider(), itemPropertyDescriptor.isSortChoices(object)); } else { result = createEDataTypeCellEditor(eDataType, composite); } } } } return result; } }