blob: 2248dbb66f7aef11d31dab4de20ca968cc5b8b3e [file] [log] [blame]
chapter:Customization[Customization]
section:ResourceManagers[Managing Resources]
section2:ResourceLoader[Resource Loader]
The class codeRef[org.eclipse.emf.parsley.resource.ResourceLoader] can be used to handle resource loading.
This class uses internally the ref:EmptyResourceInitializer[Empty Resource Initializer].
section2:EmptyResourceInitializer[Empty Resource Initializer]
If you need to initialize your model, for the first use, you can define an implementation of codeRef[org.eclipse.emf.parsley.resource.EmptyResourceInitializer].
When the main resource will be found empty, your code will be executed.
section2:EditingDomainFinder[Editing Domain Finder]
The class codeRef[org.eclipse.emf.parsley.edit.EditingDomainFinder] can be inherited to provide a specific
way to find the editign domain.
section2:ResourceSaveManager[Resource Save Manager]
Resource saving is delegated to codeRef[org.eclipse.emf.parsley.edit.ResourceSaveManager]
which, by defaults only saves the passed codeRef[org.eclipse.emf.ecore.resource.Resource].
You can inject your own save manager and implement the method code[precondition(Resource)], for
instance, you may want to validate the resource before saving, and in case the validation
fails to return code[false]. If the precondition is code[false] the default implementation
will not save the resource (and in turn will return code[false]).
section3:ValidateResourceSaveManager[Validate Resource Save Manager]
We provide an example of custom resource save manager: codeRef[org.eclipse.emf.parsley.edit.ValidateResourceSaveManager],
we show here only relevant parts to give an example:
code[Java][
public class ValidateResourceSaveManager extends ResourceSaveManager {
@Override
protected boolean precondition(Resource resource) {
return super.precondition(resource) && validateModel(resource);
}
protected boolean validateModel(Resource resource) {
for (EObject eObject : resource.getContents()) {
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eObject);
if (diagnostic.getSeverity() == Diagnostic.ERROR) {
// SKIPPED: present the errors
return false;
} else if (diagnostic.getSeverity() == Diagnostic.WARNING) {
// SKIPPED: present the warnings
}
}
return true;
}
}
]
section:Providers[Providers]
section2:FeaturesProvider[Features Provider]
e[This can be done with Parsley DSL too!]
todo[TODO: merge delle 2 versioni]
section3:FeatureProvider1[Prima versione]
To customize the e[feature list] it can be injected a codeRef[org.eclipse.emf.parsley.ui.provider.FeaturesProvider].
The default is to return the list of all the features in the EClass, but the programmer can customize it (for instance,
by returning only a superset, or using a different order) on an EClass-based strategy. The customization can be done
redefining buildMap and adding mappings.
code[Java][
protected void buildMap(EClassToEStructuralFeatureMap map) {
super.buildMap(map);
map.mapTo(LIBRARY,LIBRARY__NAME, ADDRESSABLE__ADDRESS);
}
]
In the example we specify that for the EClass e[Library] the feature that are to be displayed are e[name]
and e[address].
section3:FeatureProvider2[Seconda versione]
When the framework builds components according to the
codeRef[org.eclipse.emf.ecore.EStructuralFeature]s of a given
codeRef[org.eclipse.emf.ecore.EClass] it relies on an injected
codeRef[org.eclipse.emf.parsley.ui.provider.FeaturesProvider].
The default behavior is to simply return all the features of the a given EClass,
in the order they are defined in the EClass;
you may want to provide a custom implementation by redefining
the method code[List<EStructuralFeature> getFeatures(EClass)], or
code[List<EStructuralFeature> getFeatures(EObject)],
for instance by returning the features ordered according to their name
(the following snippet uses an utility class from the framework)
code[Java][
public class OrderedEStructuralFeaturesProvider
extends FeaturesProvider {
@Inject
EStructuralFeatureNameComparator comparator;
@Override
public List<EStructuralFeature> getFeatures(EClass eClass) {
List<EStructuralFeature> features = super.getFeatures(eClass);
Collections.sort(features,
new EStructuralFeatureNameComparator());
return features;
}
}
]
Alternatively, you can set the mappings, i.e., specify the structural
features you want to be used given an EClass, by implementing
the method code[buildMap], which receives the
codeRef[org.eclipse.emf.parsley.ui.provider.FeaturesProvider$EClassToEStructuralFeatureMap]
that can be filled with the method code[mapTo];
for instance, using the EMF extended library
example, this customization will return only the e[name] and e[address] features
for code[Library], the e[firstName], e[lastName] and e[address] for
code[Person], and the e[firstName], e[lastName] and e[books] (but
not e[address]) for code[Writer] (which inherits from code[Person]).
code[Java][
import static org.eclipse.emf.examples.extlibrary.EXTLibraryPackage.Literals.*;
import org.eclipse.emf.parsley.ui.provider.EStructuralFeaturesProvider;
public class LibraryEStructuralFeaturesProvider extends
FeaturesProvider {
@Override
protected void buildMap(EClassToEStructuralFeatureMap map) {
super.buildMap(map);
map.mapTo(LIBRARY,
LIBRARY__NAME, ADDRESSABLE__ADDRESS);
map.mapTo(PERSON,
PERSON__FIRST_NAME, PERSON__LAST_NAME,
ADDRESSABLE__ADDRESS);
map.mapTo(WRITER,
PERSON__FIRST_NAME, PERSON__LAST_NAME,
WRITER__BOOKS);
}
}
]
Another possibility is to build a map which relies on Strings
both for the codeRef[org.eclipse.emf.ecore.EClass] and for
the list of codeRef[org.eclipse.emf.ecore.EStructuralFeature];
note that the name of the codeRef[org.eclipse.emf.ecore.EClass] should
be obtained by using code[getInstanceClassName()]; you can also
combine the two approaches (in that case the map built with
code[buildMap] has the precedence):
code[Java][
import static org.eclipse.emf.examples.extlibrary.EXTLibraryPackage.Literals.*;
import org.eclipse.emf.parsley.ui.provider.FeaturesProvider;
public class LibraryEStructuralFeaturesAsStringsProvider extends
FeaturesProvider {
@Override
protected void buildMap(EClassToEStructuralFeatureMap map) {
super.buildMap(map);
map.mapTo(LIBRARY, LIBRARY__NAME, ADDRESSABLE__ADDRESS);
}
@Override
protected void buildStringMap(
EClassToEStructuralFeatureAsStringsMap stringMap) {
super.buildStringMap(stringMap);
stringMap.mapTo(PERSON.getInstanceClassName(), "firstName", "lastName",
"address");
stringMap.mapTo(WRITER.getInstanceClassName(), "firstName", "lastName",
"books");
}
}
]
section3:TableFeaturesProvider[Table Features Provider]
As an extension, you can use the codeRef[org.eclipse.emf.parsley.ui.provider.TableFeaturesProvider]:
the customizations will be applied only to ref:TableComponent[tables], not to ref:FormComponent[Forms].
section2:PropertyDescriptionProvider[Feature Caption Provider]
e[This can be done with Parsley DSL too!]
The codeRef[org.eclipse.emf.parsley.ui.provider.FeatureCaptionProvider] provides captions for
the features. It can be customized, with injection (see Injection paragraph), to customize the caption label on the
left of each control in a form and the headers in a table's columns.
The framework use a polimorphic mechanism to find customizations, so that It can
be written a method with a specific signature build by the keyword e['text'] followed by the EClass and the EStructuralFeature.
All parts of the name are separated by an underscore character and the method must accept a parameter of type EStructuralFeature.
In the following example we specify the caption text for the feature 'Author' of Book and the feature 'Name' for
Writer.
code[Java][
public String text_Book_author(final EStructuralFeature feature) {
return "Wrote by:";
}
public String text_Writer_name(final EStructuralFeature feature) {
return "Name:";
}
]
section3:FormPropertyDescriptionProvider[Form Feature Caption Provider]
The codeRef[org.eclipse.emf.parsley.ui.provider.FormFeatureCaptionProvider] can be used if you want
to define the description only for the form. For example using the ref:TreeFormComponent[Tree
Form] your definition will not be used in the tree.
In this case you can also define a method the returns directly the control, like in the example
below. In such methods there is another parameter that is the parent composite.
code[Java][
public Label label_Writer_name(Composite parent, EStructuralFeature feature) {
Label label = defaultLabel(parent, feature);
label.setBackground(getFormToolkit().getColors().getColor(IFormColors.TITLE));
return label;
}
]
section2:ViewerLabelProvider[Viewer Label Provider]
The Label Provider can be customized by providing a specific implementation of codeRef[org.eclipse.jface.viewers.ILabelProvider]
and injecting it in the spefic module e[(TODO)].
EMF Parsley provides such an implementation with the class codeRef[org.eclipse.emf.parsley.ui.provider.ViewerLabelProvider]
that is inteded to be surclassed by the programmer to provides specific implementations like in the example below.
code[Java][
public class CustomLibraryLabelProvider extends ViewerLabelProvider {
@Inject
public CustomLibraryLabelProvider(AdapterFactoryLabelProvider delegate) {
super(delegate);
}
public String text(Book book) {
return "Book: " + book.getTitle();
}
public String image(Book book) {
return "book2.png";
}
public String text(Borrower b) {
return "Borrower: " + b.getFirstName();
}
}
]
section2:ViewerContentProvider[Viewer Content Provider]
The programmer can provide a specific implementation of codeRef[org.eclipse.jface.viewers.IContentProvider]
by injecting it in the spefic module e[(TODO)]. EMF Parsley provides an implementation with the class
codeRef[org.eclipse.emf.parsley.edit.ui.provider.ViewerContentProvider] that can be easily used to
specify the children of all object on the tree, like in the example below.
code[Java][
public class CustomLibraryViewerContentProvider extends ViewerContentProvider {
@Inject
public CustomLibraryViewerContentProvider(AdapterFactory adapterFactory) {
super(adapterFactory);
}
public Object children(Library library) {
return library.getBooks();
}
public Object children(Book book) {
ArrayList<Object> children = new ArrayList<Object>();
Writer author = book.getAuthor();
if (author != null) {
children.add(author);
}
children.addAll(book.getBorrowers());
return children;
}
}
]
section2:ProposalProvider[Proposal Provider]
e[This can be done with Parsley DSL too!]
Some controls use a list of proposal to help the end user experince: for example the combo box has a
list of proposal, but also the simple text can use the proposal to assist and correct the hand-writed
values. For each feature it can be specified a list of proposals using a method that starts with the
keyword e['proposals'] followed byt the EClass and Feature undescore-character-separated.
code[Java][
public List<?> proposals_Book_author(Book book) {
List<Object> proposals = new LinkedList<Object>();
Writer writer = EXTLibraryFactory.eINSTANCE.createWriter();
writer.setFirstName("Fake");
writer.setLastName("Writer");
proposals.add(writer);
writer = EXTLibraryFactory.eINSTANCE.createWriter();
writer.setFirstName("Fake");
writer.setLastName("Writer2");
proposals.add(writer);
return proposals;
}
]
section2:ViewerContextMenuFactory[Viewer Context Menu Factory]
codeRef[org.eclipse.emf.parsley.menus.ViewerContextMenuFactory]
section2:TableColumnLabelProvider[Table Column Label Provider]
codeRef[org.eclipse.emf.parsley.ui.provider.TableColumnLabelProvider]
section:SelectionAndMenu[Selection And Menu]
section2:EmfSelectionHelper[Emf Selection Helper]
codeRef[org.eclipse.emf.parsley.util.EmfSelectionHelper]
section:Builders[Builders]
section2:TableViewerBuilder[Table Viewer Builder]
codeRef[org.eclipse.emf.parsley.builders.TableViewerBuilder]
ul[
item[ref:TableViewerColumnBuilder[TableViewerColumnBuilder]]
item[ref:ViewerInitializer[ViewerInitializer]]
]
section2:TableViewerColumnBuilder[Table Viewer Column Builder]
codeRef[org.eclipse.emf.parsley.builders.TableViewerColumnBuilder]
ul[
item[ref:JfaceProviderFactory[JfaceProviderFactory]]
item[ref:PropertyDescriptionProvider[PropertyDescriptionProvider]]
item[ref:FeaturesProvider[FeaturesProvider]]
]
section3:TableViewerEditableColumnBuilder[Table Viewer Editable Column Builder]
codeRef[org.eclipse.emf.parsley.builders.TableViewerEditableColumnBuilder]
section:Factories[Factories]
section2:FormFactory[Form Factory]
codeRef[org.eclipse.emf.parsley.factories.FormFactory]
ul[
item[ref:FormPropertyDescriptionProvider[FormPropertyDescriptionProvider]]
item[ref:FormControlFactory[Form Control Factory]]
item[ref:EditingDomainFinder[EditingDomainFinder]]
item[ref:JfaceProviderFactory[JfaceProviderFactory]]
item[ref:FeaturesProvider[FeaturesProvider]]
]
section2:JfaceProviderFactory[Jface Provider Factory]
codeRef[org.eclipse.emf.parsley.factories.ColumnLabelProviderFactory]
ul[
item[ref:ViewerLabelProvider[ViewerLabelProvider]]
item[ref:TableColumnLabelProvider[TableColumnLabelProvider]]
]
section2:FormControlFactory[Form Control Factory]
e[This can be done with Parsley DSL too!]
If you want to customize the controls on the right, it can be injected a specification of the class codeRef[org.eclipse.emf.parsley.binding.FormControlFactory].
Using the same polimorphic mechanism of the labels, the programmer can write a method with the keyword e['control']
followed by the EClass and EStructuralFeature undescore-character-separated. In the signature of the
method must be both the e[DataBinding Context] and the e[Feature Observable] that can be used for databinding.
code[Java][
public Control control_Writer_name(DataBindingContext dbc,IObservableValue featureObservable) {
//Creating the control
Text text = getToolkit().createText(getParent(), "");
text.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TREE_BORDER);
text.setBackground(getToolkit().getColors().getColor(IFormColors.TITLE));
//Binding the control to the feature observable
dbc.bindValue(SWTObservables.observeText(text, SWT.Modify), featureObservable);
return text;
}
]
For more info, see the other parts that are used internally by the e[Form Control Factory]:
ul[
item[ref:JfaceProviderFactory[JfaceProviderFactory]]
]
section2:TreeFormFactory[Tree Form Factory]
codeRef[org.eclipse.emf.parsley.factories.TreeFormFactory]
ul[
item[ref:ViewerInitializer[ViewerInitializer]]
item[ref:FormFactory[FormFactory]]
]
section2:ViewerFactory[Viewer Factory]
codeRef[org.eclipse.emf.parsley.factories.ViewerFactory]
ul[
item[ref:TableViewerBuilder[TableViewerBuilder]]
item[ref:ViewerInitializer[ViewerInitializer]]
]
section2:AdapterFactoryEditingDomain[Viewer Factory]
AdapterFactoryEditingDomain
AdapterFactory
section:Viewers[Viewers]
section2:ViewerInitializer[Viewer Initializer]
codeRef[org.eclipse.emf.parsley.viewers.ViewerInitializer]
ul[
item[e[AdapterFactoryEditingDomain]]
item[ref:ViewerContextMenuFactory[AdapterFactory]]
item[e[ILabelProvider]]
item[e[IContentProvider]]
]