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 thisEClass
((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 theclassIcon
annotation.classIcon
: Defines the icon of the instances of theEClass
.
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).
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;
}