Monday, June 30, 2008
Solipse for Eclipse on solaris-gtk-x86
Thanks to everyone who sent suggestions and who found some use for the initial scripts, and please feel welcome on the Solipse community site!
Saturday, June 28, 2008
Edit EMF Tree Nodes Inline
The problem to solve: to edit a specific property inline in a tree editor generated by EMF.
For this example, we will be using a tree editor for UML. For any UML NamedElement, we would like to be able to edit the name directly in the tree editor.
1. We will generate the UML.genmodel using the UML.ecore file from eclipse cvs
- host: dev.eclipse.org
- repository path: /cvsroot/modeling
- location: org.eclipse.mdt/org.eclipse.uml2/plugins/org.eclipse.uml2.uml/model/UML.ecore
With the UML.genmodel file, emit the UML Model, Edit and Editor code. This custom UML editor is only used for this example. You may very well have a different model editor in mind for customization.
2. We have the UML model code (the domain objects and the factories to create those domain objects), UML edit code (the Item Providers and Item Provider adapter factory for the domain objects) and UML editor in three separate plug-ins. We can call these uml.inline.editing.example (for the model), uml.inline.editing.example.edit (for the item providers) and uml.inline.editing.example.editor (for the editor).
3. We want to make sure that the NamedElementItemProvider implements org.eclipse.emf.edit.provider.IUpdateableItemText because we want to be able to update the name property of NamedElements inline. The two methods we would like to include look like this:
public void setText(Object o, String s) {
if (!(o instanceof NamedElement)) {
return;
}
NamedElement namedElement = (NamedElement) o;
if ("".equals(s) && !namedElement.isSetName()) {
return;
}
IEditorPart activeEditor = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage().getActiveEditor();
if (activeEditor instanceof IEditingDomainProvider) {
EditingDomain editingDomain = ((IEditingDomainProvider) activeEditor)
.getEditingDomain();
editingDomain.getCommandStack().execute(
SetCommand.create(editingDomain, namedElement,
UmlPackage.eINSTANCE.getNamedElement_Name(), s));
} else {
namedElement.setName(s);
}
}
@Override
public String getUpdateableText(Object o) {
if (o instanceof NamedElement) {
NamedElement namedElement = (NamedElement) o;
if (namedElement.getName() == null) {
return "";
}
return namedElement.getName();
}
return super.getUpdateableText(o);
}
Keep in mind that the superclass org.eclipse.emf.edit.provider.ItemProviderAdapter already includes a method #getUpdateableText(Object).
4. We need to make sure the UMLItemProviderAdapterFactory will adapt NamedElements to this IUpdateableText item provider. For this, we will need to add IUpdateableText.class to the supported types in the constructor. The generated code is in grey:
public UmlItemProviderAdapterFactory() {
supportedTypes.add(IUpdateableItemText.class);
supportedTypes.add(IEditingDomainItemProvider.class);
supportedTypes.add(IStructuredItemContentProvider.class);
supportedTypes.add(ITreeItemContentProvider.class);
supportedTypes.add(IItemLabelProvider.class);
supportedTypes.add(IItemPropertySource.class);
}
What if we want to set the focus of the UMLEditor on the updateable field as soon as the NamedElement is created?
By default, if we were to hit SPACE when a NamedElement node is selected, the cell editor would gain focus. Suppose we want the cell editor to have focus automatically whenever a new NamedElement is created.
For this we can modify the CommandStackListener in the generated UMLEditor to focus the cell editor in the tree whenever a new child or sibling NamedElement is created in the tree editor. Generated code is in grey:commandStack.addCommandStackListener(new CommandStackListener() {
public void commandStackChanged(final EventObject event) {
getContainer().getDisplay().asyncExec(new Runnable() {
public void run() {
firePropertyChange(IEditorPart.PROP_DIRTY);
// Try to select the affected objects.
//
Command mostRecentCommand = ((CommandStack) event
.getSource()).getMostRecentCommand();
if (mostRecentCommand != null) {
setSelectionToViewer(mostRecentCommand
.getAffectedObjects());
// set the focus on the editable tree cell
if (currentViewer instanceof TreeViewer
&& (mostRecentCommand instanceof CreateChildCommand)) {
Tree tree = ((TreeViewer) currentViewer)
.getTree();
TreeItem[] treeItems = tree.getSelection();
if (treeItems.length == 1) {
Event enableEditField = new Event();
enableEditField.button = 1;
enableEditField.x = treeItems[0].getBounds().x;
enableEditField.y = treeItems[0].getBounds().y;
tree.notifyListeners(SWT.Selection, enableEditField);
tree.notifyListeners(SWT.MouseDown, enableEditField);
tree.notifyListeners(SWT.MouseUp, enableEditField);
}
}
}
if (propertySheetPage != null
&& !propertySheetPage.getControl().isDisposed()) {
propertySheetPage.refresh();
}
}
});
}
});
It is just that easy to specify a default property for direct inline editing in a generated EMF editor!
The name cell editor is focused.
The label is focused.