Dimitry Karpenko
Java/Eclipse developer in MyEclipse and Webclipse teams.
Java/Eclipse developer in MyEclipse and Webclipse teams.
In previous articles, we’ve learned how to perform relatively simple Eclipse Sapphire customizations. Let’s try out something more complex. We’ll be creating one more editor for the android resources. This time our editor will handle not only color resources, but also another node representing string resources which are stored in another file, strings.xml.
Of course, you need to understand how to use the Eclipse editor and Sapphire API. Also, please read the Custom Bindings article to familiarize yourself with concepts that will be used in this article. You need Eclipse 4 and Sapphire 9. If you are using a different version you can follow along but you may encounter some differences from what is described.
Note: You can read about creating a simple Eclipse Sapphire editor here.
The model is pretty simple and similar to the model in a previous article in which both Color and String have Name and Value properties. You can look at the `com.genuitec.sapphire.integratededitor.model` package in the sample project to see details. `IAndroidResources` is an actual root model class, it holds colors and strings lists. `IIntegratedAndroidResources` and `IStringResources` are dummy model classes needed by Sapphire’s model-to-resources connection code, see below for details.
The core part of our editor is the `AndroidResourcesEditor` class. We’ll need to create two separate source pages for editing colors.xml and strings.xml. Method `createSourcePages()` is responsible for doing this.
Important: While reading the code, be sure not to confuse the following:
To handle two separate model files, we need to have two model objects: `IAndroidResources` (having all of our properties) and `IIntegratedAndroidResources` (a dummy type to be bound with the resource representing strings.xml). Strings property in `IAndroidResources` type has our custom annotation `@IntegratedListBinding`. This annotation doesn’t provide any data and serves as a marker annotation indicating that the specified property should be persisted in a “foreign” file, in our case strings.xml.
To have a single editor for two xml files, we’ll need to have our model bound to 2 different `RootXmlResource` entities. Let’s see how it’s done. Take a look at the method `createModel()`.
protected Element createModel() { XmlEditorResourceStore foreignResStore = new XmlEditorResourceStore( this, this.stringsSourceEditor ); foreignResource = new RootXmlResource( foreignResStore ); RootXmlResource mainRes = createMainResource(); this.androidResources = applicationElementType.instantiate( mainRes ); foreignResource.init(androidResources); this.integratedAndroidResources = integratedAppElementType.instantiate( new RootIntegratedResource(mainRes, foreignResource, this.androidResources, applicationElementType ) ); return this.integratedAndroidResources; }
protected RootXmlResource createMainResource() { RootXmlResource mainRes = new RootXmlResource( new XmlEditorResourceStore( this, this.colorsSourceEditor ) ) { @Override protected PropertyBinding createBinding(Property property) { PropertyDef propertyDef = property.definition(); PropertyBinding binding = null; if (propertyDef instanceof ListProperty) { final IntegratedListBinding customBindingAnnotation = propertyDef.getAnnotation(IntegratedListBinding.class); if (customBindingAnnotation != null) { binding = new CustomizedXmlBindingImpl((XmlResource) foreignResource); return binding; } } return super.createBinding(property); } }; return mainRes; }
Here we create `RootXmlResource` with overriding `createBinding()` method. In this method, we analyze the bound field for a presence of marker `IntegratedListBinding` annotation. If annotation is present, we create `CustomizedXmlBindingImpl` binding impl, which is responsible for storing changes for specified property to “foreign” resource.
The `createFormPages()` method is responsible for creating Design page. Other methods in `AndroidResourcesEditor` are pretty straightforward.
`CustomizedXmlBindingImpl` is responsible for binding some model property to a custom resource. Most of it is copied from the original Sapphire’s `StandardXmlListBindingImpl` with changes allowing it to use the custom resource (stored in `xmlResource`) field. If you need to create a binding for some other property type (Value, Element, Implied Element), you’ll need to do the same; look at the original binding code, extend the original binding class and modify its behavior to use custom resource. Some methods are copied instead of extending, because there’s a lot of private or final stuff in Sapphire code.
This class is aggregating two underlined resources – for colors.xml and strings.xml. It’s responsible to call `save()` for both resources when editor save is called.
The ResEditor.sdef file describes simple Sapphire GUI for our editor. The Editor should be registered in plugin.xml, some details on doing this can be found here: http://www.eclipse.org/sapphire/releases/9.0.4/documentation/introduction/index.html.
You’ll need to create a sample project in your test workspace, or you can use an existing one. You will need to place two xml files, colors.xml and strings.xml, inside the same folder in your project. Sample files can be downloaded using the link below. Double-click colors.xml to launch your editor.
sapphire_inteditor_tutorial—Sample project
XMLfiles.zip—Sample colors.xml and strings.xml files
Coding Tip: Using Custom Bindings for Property Editing in Sapphire
Creating Custom Editors in Sapphire
If you have any comments or questions, we would love to hear from you @MyEclipseIDE on twitter or via the MyEclipse forum. Happy coding!