Skip to content

Exeed (Extended EMF Editor)

Exeed is an extended version of the built-in tree-based reflective editor provided by EMF. The aim of Exeed is to enable developers to customize the appearance of the editor (labels and icons) by annotating Ecore metamodels. As a result, developers can enjoy the benefits of a customized editor for their models without needing to generate one and then customize it using Java.

EMF Reflective Editor Exeed

Exeed Annotations Keys

The source for exeed annotations is exeed. Exeed annotations are only supported in EClass, EEnumLiteral and EStructuralFeature elements of the metamodel. For each element the following keys are supported:

EClass

  • label: Defines the label that will be used to for the element when it is displayed on all views related to the editor (editing tree, properties view, etc.)
  • referenceLabel: Defines the label for a reference to an instance of this EClass ((e.g. in the properties view).
  • icon: Defines the icon to use to display alongside the element on all views related to the editor (editing tree, properties view, etc.). If specified, it overrides the classIcon annotation.
  • classIcon: Defines the icon of the instances of the EClass.

EEnumLiteral

  • label: Defines the label that will be used for the enumeration literal when it is displayed on all views related to the editor (editing tree, properties view, etc.)

EStructuralFeature

  • featureLabel: Defines the label that will be used for the structural feature when it is displayed on all views related to the editor (editing tree, properties view, etc.)

Exeed Annotations Values

All keys, except for classIcon, accept an EOL script as their value. This allows labels and icons to be dynamically allocated based on the properties of the instance. The EOL script is evaluated in the context of each instance, that is, the current instance can be accessed via the self keyword. Further, all other model elements are accessible via navigation (i.e. references from the instance) or by getting all elements of a type (e.g. MyType.all).

For the icon and classIcon keys the expected value is the name of one of the built-in icons available in Exeed (excluding the file extension -- i.e. model instead of model.gif), or a fully-qualified Eclipse platform URI (see the Package class in the metamodel below for an example).

Example

The images show the tree view of an OO model with the default EMF reflective editor (left) and Exeed (right).

EMF Reflective EditorExeed Editor

Below is the annotated OO metamodel (in Emfatic) that was used to obtain the Exeed result above (the example is available from the examples folder of the Git repository):

@namespace(uri="OO", prefix="")
package OO;

@exeed(classIcon="model")
class Model extends Package {
}

@exeed(referenceLabel="
var str : String;
str = self.closure(pe:PackageableElement|pe.package).collect(p|p.name).invert().concat('.');
if (self.package.isDefined()){
    str = str + '.';
}
str = str + self.name;
return str;
")
abstract class PackageableElement extends NamedElement {
  !ordered ref Package[1]#contents ~package;
}

abstract class AnnotatedElement {
  !ordered val Annotation[*] annotations;
}

@exeed(label="return self.key + ' -> ' + self.value;", classIcon="annotation")
class Annotation {
  !unique !ordered attr String[1] key;
  !unique !ordered attr String[1] value;
}

@exeed(label="return self.name;")
abstract class NamedElement extends AnnotatedElement {
  !unique !ordered attr String[1] name;
}

@exeed(classIcon="platform:/resource/org.eclipse.epsilon.examples.exeedoo/icons/package.gif", label="return self.name;")
class Package extends PackageableElement {
  !ordered val PackageableElement[*]#~package contents;
  ref Package[*] uses;
}

abstract class Classifier extends PackageableElement {
}

class ExternalClass extends Class {
}

@exeed(classIcon="class", label="
var label : String;
label = self.name;
if (self.extends.isDefined()){
    label = label + ' extends ' + self.extends.name;
}
return label;
")
class Class extends Classifier {
  !ordered ref Class[1]#extendedBy ~extends;
  !ordered ref Class[*]#~extends extendedBy;
  !ordered val Feature[*]#owner features;
  !unique !ordered attr Boolean[1] isAbstract;
}

@exeed(classIcon="datatype")
class Datatype extends Classifier {
}

abstract class Feature extends NamedElement {
  !ordered ref Class[1]#features owner;
  !ordered ref Classifier[1] type;
  !unique !ordered attr VisibilityEnum[1] visibility;
}

@exeed(label="
var label : String;
label = self.name;
if (self.type.isDefined()){
    if (self.isMany) {
        label = label + ' [*]';
    }
    label = label + '  : ' + self.type.name;
}
return label;", 
icon="
if (self.visibility = VisibilityEnum#private) {
    return 'private';
}
else {
    return 'public';
}
")
abstract class StructuralFeature extends Feature {
  !unique !ordered attr Boolean[1] isMany;
}

@exeed(label="
var label : String;
label = self.name + ' (';
for (p in self.parameters) {
    label = label + p.name;
    if (p.type.isDefined()) {
        label = label + ' : ' + p.type.name;
    }
    if (hasMore) {
        label = label + ', ';
    }
}
label = label + ')';
if (self.type.isDefined()) {
    label = label + ' : ' + self.type.name;
}
return label;
", classIcon="operation")
class Operation extends Feature {
  !ordered val Parameter[*]#owner parameters;
}

@exeed(label="
var label : String;
label = self.name;
if (self.type.isDefined()){
    label = label + ' : ' + self.type.name;
}
return label;
", classIcon="parameter")
class Parameter extends NamedElement {
  !ordered ref Classifier[1] type;
  !ordered ref Operation[1]#parameters owner;
}

class Reference extends StructuralFeature {
}

class Attribute extends StructuralFeature {
}

enum VisibilityEnum {
  public = 1;
  private = 2;
}

Resources