GMF

EDataTypes in GMF allow you to specify custom data types in an Ecore model. In this page I will try and describe the steps to create your own editor to a custom data type, in particular an editor that allows the user to select a file.

  1. Create an EDataType, specifying the Name and the Instance Class Name.
  2. Create the new data types somewhere in your project, e.g. FileReference interface and the FileReferenceImpl implementation.
  3. Create another EClass somewhere that uses this EDataType in an EAttribute.

If you now connect this new EClass to your .gmfgraph/.gmfgen/.gmfmodel, you will end up with an editor that accepts text input, but just throws IllegalArgumentExceptions. This will occur if you have set the EDataType as serialized.

(If no properties show up for your new EClass, try deleting the edit plugin.xml.)

To resolve this, you will have to go into the FactoryImpl for the package the datatype resides, and edit createFileReferenceFromString() and convertFileReferenceToString():

/**
 * @generated NOT
 */
public FileReference createFileReferenceFromString(EDataType eDataType, String initialValue) {
  return new FileReferenceImpl(initialValue);
}

/**
 * @generated NOT
 */
public String convertFileReferenceToString(EDataType eDataType, Object instanceValue) {
  if (instanceValue == null)
    return null;
  return ((FileReference) instanceValue).toString();
}

The strings passed here will now be saved in the model file. The next step is to provide a dialog for editing the Strings, and not just a String editor.

Following a newsgroup discussion that was hard to find, the solution is to modify the generated diagram.sheet.XXXPropertySection like so:

public IPropertySource getPropertySource(Object object) {
  if (object instanceof IPropertySource) {
    return (IPropertySource) object;
  }
  AdapterFactory af = getAdapterFactory(object);
  if (af != null) {
    IItemPropertySource ips = (IItemPropertySource) af.adapt(object,
        IItemPropertySource.class);
    if (ips != null) {
      return new CustomisedPropertySource(object, ips); // new code!!!
    }
  }
  if (object instanceof IAdaptable) {
    return (IPropertySource) ((IAdaptable) object)
        .getAdapter(IPropertySource.class);
  }
  return null;
}

This refers to additional classes, which are as follows:

public class CustomizedPropertyDescriptor extends PropertyDescriptor implements IPropertyDescriptor {
  public CustomizedPropertyDescriptor(Object object,
      IItemPropertyDescriptor itemPropertyDescriptor) {
    super(object, itemPropertyDescriptor);
  }

  @Override
  protected CellEditor createEDataTypeCellEditor(EDataType dataType,
      Composite composite) {
    if (dataType.equals( DomainPackage.eINSTANCE.getFileReference() )) {
      System.out.println("kittens!");  // success!
    }
    return super.createEDataTypeCellEditor(dataType, composite);
  }
}
public class CustomisedPropertySource extends PropertySource implements IPropertySource {
  public CustomisedPropertySource(Object object,
      IItemPropertySource itemPropertySource) {
    super(object, itemPropertySource);
  }

  protected IPropertyDescriptor createPropertyDescriptor(
      IItemPropertyDescriptor itemPropertyDescriptor) {
    return new CustomizedPropertyDescriptor(object, itemPropertyDescriptor);
  }
}

However, in order to deal with EDataTypes, you must also go through an EDataTypeValueHandler.